﻿using System;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 扩展方法集中类 
/// </summary>
public static class ExtendMethods
{
    /// <summary>
    /// 将Bool数组中的变量重新设置为你需要的值
    /// </summary>
    /// <param name="array">需要设置的数组</param>
    /// <param name="value">具体参数</param>
    /// <returns></returns>
    public static void InitValue(this bool[] array, bool value)
    {
        for (int i = 0, count = array.Length; i < count; i++)
        {
            array[i] = value;
        }
    }

    /// <summary>
    /// 获取某一个节点下的全部子节点 
    /// </summary>
    /// <param name="parent"></param>
    /// <returns></returns>
    public static Transform[] GetChildArray(this Transform parent)
    {
        int count = parent.childCount;
        if (count == 0)
        {
            return null;
        }
        Transform[] list = new Transform[count];

        for (int i = 0; i < count; i++)
        {
            list[i] = parent.GetChild(i);
        }

        return list;
    }

    /// <summary>
    /// 根据name返回数组
    /// </summary>
    /// <param name="parent"></param>
    /// <param name="name"></param>
    /// <returns></returns>
    public static List<Transform> GetChildListByName(this Transform parent, string name)
    {
        int count = parent.childCount;
        if (count == 0)
        {
            return null;
        }
        List<Transform> list = new List<Transform>();

        for (int i = 0; i < count; i++)
        {
            if (parent.GetChild(i).name.Contains(name))
            {
                list.Add(parent.GetChild(i));
            }
        }

        return list;
    }

    /// <summary>
    /// 将数组转换为list 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="array"></param>
    /// <returns></returns>
    public static List<T> ToList<T>(this T[] array)
    {
        List<T> temp = new List<T>();
        for (int i = 0, count = array.Length; i < count; i++)
        {
            temp.Add(array[i]);
        }
        return temp;
    }

    /// <summary>
    /// 字符串NullOrEmpty判断 
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsNullOrEmpty(this string str)
    {
        return string.IsNullOrEmpty(str);
    }


    public static Transform FindChild(this GameObject go, string name)
    {
        return go.transform.FindChild(name);
    }

    public static Transform FindChild(this MonoBehaviour mb, string name)
    {
        return mb.transform.FindChild(name);
    }

    /// <summary>
    /// 将字典中的值重写。
    /// </summary>
    /// <typeparam name="K"></typeparam>
    /// <typeparam name="V"></typeparam>
    /// <param name="dict"></param>
    /// <param name="copy"></param>
    /// <param name="overwrite">该值决定是否重写</param>
    public static void AddRange<K, V>(this Dictionary<K, V> dict, Dictionary<K, V> copy, bool overwrite)
    {
        if (copy == null)
        {
            return;
        }

        foreach (KeyValuePair<K, V> pair in copy)
        {
            if (dict.ContainsKey(pair.Key) && overwrite)
            {
                dict[pair.Key] = pair.Value;
            }
            else
            {
                dict.Add(pair.Key, pair.Value);
            }
        }
    }

    /// <summary>
    /// 增加或者更新值
    /// </summary>
    /// <typeparam name="K"></typeparam>
    /// <typeparam name="V"></typeparam>
    /// <param name="dict"></param>
    /// <param name="k"></param>
    /// <param name="v"></param>
    public static void AddOrUpdate<K, V>(this IDictionary<K, V> dict, K k, V v)
    {
        if (dict.ContainsKey(k))
        {
            dict[k] = v;
        }
        else
        {
            dict.Add(k, v);
        }
    }

    /// <summary>
    /// 设置游戏物体的状态，公共状态  
    /// </summary>
    /// <param name="_object"></param>
    /// <param name="_active"></param>
    public static void SetActive(this GameObject _object, bool _active)
    {
        if (_object.activeInHierarchy == _active)
            return;
        _object.SetActive(_active);
    }

    /// <summary>
    /// 设置游戏物体的状态，自身状态 
    /// </summary>
    /// <param name="_object"></param>
    /// <param name="_active"></param>
    public static void SetActiveSelf(this GameObject _object, bool _active)
    {
        if (_object.activeSelf == _active)
            return;
        _object.SetActive(_active);
    }

    /// <summary>
    /// 设置游戏物体的状态，公共状态  
    /// </summary>
    /// <param name="_object"></param>
    /// <param name="_active"></param>
    public static void SetActive(this Transform _transform, bool _active)
    {
        SetActive(_transform.gameObject, _active);
    }

    /// <summary>
    /// 设置游戏物体的状态，自身状态 
    /// </summary>
    /// <param name="_transform"></param>
    /// <param name="_active"></param>
    public static void SetActiveSelf(this Transform _transform, bool _active)
    {
        SetActiveSelf(_transform.gameObject, _active);
    }

    /// <summary>
    /// 将数组中的所有数据初始化为某一个值
    /// </summary>
    /// <param name="array"></param>
    /// <param name="value"></param>
    public static void InitOfValue(this bool[,] array, bool value)
    {
        for (int i = 0, ilength = array.GetLength(0); i < ilength; i++)
        {
            for (int j = 0, jlength = array.GetLength(1); j < jlength; j++)
            {
                array[i, j] = value;
            }
        }
    }

    /// <summary>
    /// 将二维数组中的所有数据初始化为某一个值
    /// </summary>
    /// <param name="array"></param>
    /// <param name="value"></param>
    public static void InitOfValue(this int[,] array, int value)
    {
        for (int i = 0, ilength = array.GetLength(0); i < ilength; i++)
        {
            for (int j = 0, jlength = array.GetLength(1); j < jlength; j++)
            {
                array[i, j] = value;
            }
        }
    }

    /// <summary>
    /// 判断物体是否在某一个摄像机的视角内 
    /// </summary>
    /// <param name="render"></param>
    /// <param name="camera"></param>
    /// <returns></returns>
    public static bool IsVisibleFrom(this Renderer render, Camera camera)
    {
        bool visible = true;
        // 取得给定的摄像机的视景并返回它的六个面。
        Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
        // 判断边界框是否在平面内部 
        visible = GeometryUtility.TestPlanesAABB(planes, render.bounds);
        return visible;
    }

    /// <summary>
    /// 转换为Vector2，即去掉z轴。
    /// </summary>
    /// <param name="vec"></param>
    /// <returns></returns>
    public static Vector2 ToVector2(this Vector3 vec)
    {
        return new Vector2(vec.x, vec.y);
    }

    /// <summary>
    /// 转换为Vector3，使用某一个值填充 
    /// </summary>
    /// <param name="vec"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public static Vector3 ToVector3(this Vector2 vec, float value = 0)
    {
        return new Vector3(vec.x, vec.y, value);
    }

    /// <summary>
    /// 计算某一个数值的顺序，基于传入参数 
    /// </summary>
    /// <param name="curnum"></param>
    /// <param name="num1"></param>
    /// <param name="num2"></param>
    /// <returns></returns>
    public static bool Order(float curnum, float num1, float num2)
    {
        if (curnum > num1 && curnum < num2)
        {
            return true;
        }
        else if (curnum > num2 && curnum < num1)
        {
            return true;
        }
        else
            return false;
    }

    /// <summary>
    /// 判断某个数值是否在指定范围内
    /// </summary>
    /// <param name="_value"></param>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public static bool Order(int _value, int min, int max)
    {
        if (_value >= min && _value <= max)
            return true;
        return false;
    }

    /// <summary>
    /// 格式化小数点后面的位数 
    /// </summary>
    /// <param name="num"></param>
    /// <param name="count"></param>
    /// <returns></returns>
    public static float Format(this float num, int count)
    {
        return Mathf.FloorToInt(num * Mathf.Pow(10, count)) / Mathf.Pow(10, count);
    }

    /// <summary>
    /// 将右屏坐标转换为左屏坐标 
    /// </summary>
    /// <param name="rightpath"></param>
    /// <returns></returns>
    public static Vector3[] GetLeftPath(Vector3[] rightpath)
    {
        Vector3[] tempVec = rightpath;

        for (int i = 0, count = rightpath.Length; i < count; i++)
        {
            /*
             * 左边路径坐标和右边相差11.2个单位，因为左边坐标比右边坐标小，应该减去11.2个单位 
             */
            tempVec[i].x = rightpath[i].x - 11.2f;
        }

        return tempVec;
    }

    /// <summary>
    /// 弧度转角度
    /// </summary>
    /// <param name="radian"></param>
    /// <returns></returns>
    public static float RadianToAngle(float radian)
    {
        return radian * 180 / Mathf.PI;
    }

    /// <summary>
    /// 角度转弧度 
    /// </summary>
    /// <param name="angle"></param>
    /// <returns></returns>
    public static float AngleToRadian(float angle)
    {
        return angle * Mathf.PI / 180;
    }

    /// <summary>
    /// 计算两个点之间的夹角，仅用于2D界面(x，y轴)
    /// </summary>
    /// <param name="targetPos"></param>
    /// <returns></returns>
    public static float CalcAngleFromPosition(Vector3 sourcePos, Vector3 targetPos)
    {
        return RadianToAngle(Mathf.Atan((sourcePos.y - targetPos.y) / (sourcePos.x - targetPos.x)));
    }

    /// <summary>
    /// 计算两个点的距离，只计算x，y轴，用于2D平面 
    /// </summary>
    /// <param name="source"></param>
    /// <param name="target"></param>
    /// <returns></returns>
    public static float CalcDistance2D(Vector3 source, Vector3 target)
    {
        return Vector2.Distance(source.ToVector2(), target.ToVector2());
    }

    /// <summary>
    /// 分解该数字 
    /// </summary>
    /// <param name="Num"></param>
    /// <returns></returns>
    public static int[] DecomposeNum(this int Num)
    {
        List<int> tempList = new List<int>();
        int tempNum = Num;

        for (int i = 0; i < 10; i++)
        {
            tempList.Add(tempNum % 10);
            tempNum /= 10;

            if (tempNum == 0)
                break;
        }

        tempList.Reverse();

        return tempList.ToArray();
    }

    /// <summary>
    /// 设置当前节点及其子节点全部Layer
    /// </summary>
    /// <param name="_trans"></param>
    /// <param name="_layer"></param>
    public static void SetLayer(this Transform _trans, int _layer)
    {
        Transform[] child = _trans.GetComponentsInChildren<Transform>();
        for (int i = 0, count = child.Length; i < count; i++)
        {
            child[i].gameObject.layer = _layer;
        }
    }

    /// <summary>
    /// 更新链表中的某一个值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="_list"></param>
    /// <param name="index"></param>
    /// <param name="_t"></param>
    /// <returns></returns>
    public static bool UpdateListByItem<T>(this List<T> _list, int index, T _t)
    {
        if (_list.Count <= index)
            return false;

        _list[index] = _t;
        return true;
    }

    /// <summary>
    /// 返回浮点数的整数部分 
    /// </summary>
    /// <param name="_value"></param>
    /// <returns></returns>
    public static int ToInt(this float _value)
    {
        return Mathf.FloorToInt(_value);
    }

    public static Transform CreateChild(this Transform _trans, string childname = "")
    {
        return CreateChild(_trans.gameObject, childname).transform;
    }

    public static GameObject CreateChild(this GameObject _father, string childname = "")
    {
        GameObject child = new GameObject(childname.IsNullOrEmpty() ? "child" : childname);
        child.transform.SetParent(_father.transform);
        child.transform.localPosition = Vector3.zero;
        child.transform.localRotation = Quaternion.identity;
        child.transform.localScale = Vector3.one;

        return child;
    }

    /// <summary>
    /// 使用指定的预制体，生成子节点 
    /// </summary>
    /// <param name="_father"></param>
    /// <param name="_prefab"></param>
    /// <param name="childname"></param>
    /// <returns></returns>
    public static GameObject CreateChildForPrefab(this GameObject _father, GameObject _prefab, string childname = "")
    {
        GameObject child = GameObject.Instantiate(_prefab);
        if (!childname.IsNullOrEmpty())
        {
            child.name = childname;
        }
        child.transform.SetParent(_father.transform);
        child.transform.localPosition = Vector3.zero;
        child.transform.localRotation = Quaternion.identity;
        child.transform.localScale = Vector3.one;

        return child;
    }

    public static Transform CreateChildForPrefab(this Transform _father, GameObject _prefab, string childname = "")
    {
        return _father.gameObject.CreateChildForPrefab(_prefab, childname).transform;
    }

    /// <summary>
    /// 日期转换成unix时间戳
    /// </summary>
    /// <param name="dateTime"></param>
    /// <returns></returns>
    public static string DateTimeToUnixTimestampLocalTime(this DateTime dateTime)
    {
        DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
        return (dateTime - startTime).TotalSeconds.ToString();
    }

    /// <summary>
    /// unix时间戳转换成日期
    /// </summary>
    /// <param name="unixTimeStamp">时间戳（秒）</param>
    /// <returns></returns>
    public static DateTime UnixTimestampToDateTimeLocalTime(string timestamp)
    {
        DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
        long lTime = long.Parse(timestamp + "0000000");
        TimeSpan toNow = new TimeSpan(lTime);
        return dtStart.Add(toNow);
    }

    /// <summary>
    /// 返回第一个相同变量的序列号 
    /// </summary>
    /// <param name="array"></param>
    /// <param name="_t"></param>
    /// <returns></returns>
    public static int GetValueIndex(this string[] array, string _t)
    {
        int index = -1;
        for (int i = 0, count = array.Length; i < count; i++)
        {
            if (array[i].Equals(_t))
            {
                index = i;
                break;
            }
        }
        return index;
    }
}